import multiprocessing
import os
import datetime as dt
import sys
from sklearn.ensemble import GradientBoostingClassifier
import pandas as pd

join = os.path.join
dirname = os.path.dirname
CURRENT_PATH = dirname(os.path.realpath(__file__))

sys.path.append(CURRENT_PATH)
from utils_tsfresh import gen_X_y_data,gen_proc_basedata,get_model_performance1,\
get_model_performance2,gen_Y,gen_train_test,rolling_extract_genX, time_log

SAVE_PATH = ''
DATA_PATH = join(dirname(CURRENT_PATH), 'DataAssets')
if_use_mpp = False
mpp_num = 3

'''
使用tsfresh模块衍生自变量，查看不同时序长度下，算法类特征预测效果，此处使用多进程跑批。

input : csv 数据集
input : obj 跑批配置对象
output: csv 模型跑批后结果指标
'''

settings = ComprehensiveFCParameters() # default features

tsfresh_featurenames = ['approximate_entropy','binned_entropy','energy_ratio_by_chunks',
'fourier_entropy','permutation_entropy','sample_entropy','agg_linear_trend','benford_correlation',
'c3','cid_ce','cwt_coefficients','fft_aggregated','fft_coefficient',
'friedrich_coefficients','lempel_ziv_complexity','linear_trend','linear_trend_timewise',
'matrix_profile','max_langevin_fixed_point','set_property','spkt_welch_density',
'symmetry_looking','time_reversal_asymmetry_statistic']

default_settings_features = {}
for i in settings.keys():
    if i in feature_new:
        default_settings_features[i] = settings[i]

def train_main(vals, train_config):

    one_result = []
    max_timeshift, min_timeshift, min_timeseries = vals # 数据解包
    print(f'processing.... max_timeshift:{max_timeshift}, min_timeshift:{min_timeshift}, min_timeseries:{min_timeseries}')

    train_config['max_timeshift'] = max_timeshift
    train_config['min_timeshift'] = min_timeshift
    train_config['min_timeseries'] = min_timeseries

    data_pred, predcit_asccode = gen_proc_basedata(DATA_PATH, train_config)
    data_pred = data_pred.loc[data_pred['date'] < dt.datetime.strptime(train_config['split_date'] , '%Y-%m-%d')]

    ####################################### 生成X-Y
    X_Data = rolling_extract_genX(data_pred, train_config)
    y_Data = gen_Y(data_pred)

    X_y_data_total = gen_X_y_data(X_Data, y_Data, predcit_asccode , train_config)
    X_y_data_train, X_y_data_test, X_data_train, y_data_train, X_data_test, y_data_test = \
        gen_train_test(X_y_data_total, train_config)

    ####################################### 模型跑批，获取结果
    regressor = GradientBoostingClassifier(n_estimators=250,max_depth=7, subsample=0.85, random_state=0 , n_jobs=0)
    regressor.fit(X_data_train, y_data_train)
    y_data_test_pred = regressor.predict(X_data_test)

    model_mae, \
    model_rmse = get_model_performance1(y_data_test, y_data_test_pred)

    upper_15, \
    upper_10, \
    upper_5, _ = get_model_performance2(X_y_data_test['val_y'], y_data_test_pred)

    one_result.append(model_mae)
    one_result.append(model_rmse)
    one_result.append(upper_5)
    one_result.append(upper_10)
    one_result.append(upper_15)
    one_result.append('|'.join([str(max_timeshift), str(min_timeshift), str(min_timeseries)]))
    one_result_df = pd.DataFrame(one_result).T
    one_result_df.columns = ['mae','rmse','upper_5%' , 'upper_10%' , 'upper_15%' , 'model_info']

    ######################################## 结果输出
    result_name = f'{max_timeshift}_{min_timeshift}_{min_timeseries}_result_report.csv'
    result_name2 = f'{max_timeshift}_{min_timeshift}_{min_timeseries}_result_feature.csv'

    one_result_df.to_csv(join(SAVE_PATH , result_name) , index = False)
    feature_imp = pd.DataFrame(list(zip(X_data_test.columns,   regressor.feature_importances_)))
    feature_imp.to_csv(join(SAVE_PATH, result_name2))

def summary_model_report():
    files = sorted(os.listdir(SAVE_PATH))
    files_list = [i for i in files if '_result_report.csv' in i]

    datas = [pd.read_csv(join( SAVE_PATH,i)) for i in files_list]
    all_data = pd.concat(datas)

    all_data.to_excel( join(SAVE_PATH, 'all_summary_model_report.xlsx'),index=False)
    print('all finish !!!!')

@time_log('模型跑批')
def main():
    if if_use_mpp == True:
        mpp = multiprocessing.Pool(processes=mpp_num)

    for max_timeshift in max_timeshift_list:
        for min_timeshift in min_timeshift_list:
            for min_timeseries in min_timeseries_list:

                vals = [max_timeshift, min_timeshift, min_timeseries]
                if if_use_mpp:
                    mpp.map_async(train_main, [vals])
                else:
                    train_main(vals)
    if if_use_mpp:
        mpp.close()
        mpp.join()

    summary_model_report()

if __name__ == '__main__':
    
    max_timeshift_list = [3, 6, 9, 12]
    min_timeshift_list = [1, 3, 6]
    min_timeseries_list = [12] # 这个参数视为占位符，无实际意义
    
    iter_config = {
        'max_timeshift': '',
        'min_timeshift': '',
        'min_timeseries': '',
        'split_date': '2021-07-01',
        'model_version': 1,
        'tsfresh_feature':default_settings_features
    }
    
    main()
